from django.shortcuts import render, get_object_or_404, redirect
from django.core.paginator import Paginator
from django.db.models import Avg, Q
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import Category, SubCategory, ProductType, Product, CartItem
import json
from django.http import JsonResponse
import hashlib
from django.urls import reverse


def product_list(request):
    """
    商品列表视图 - 显示所有上架商品
    支持排序和分页，可通过AJAX加载更多商品(无限滚动)
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的商品列表页面
    """
    # 处理Ajax请求时不使用缓存
    if request.GET.get('ajax') == '1':
        return _product_list_uncached(request)
    
    return _product_list_uncached(request)


def _product_list_uncached(request):
    """
    商品列表视图的非缓存版本 - 内部实现函数
    获取商品数据，处理排序、分页等逻辑
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的商品列表页面或部分HTML(AJAX请求)
    """
    # 获取所有上架商品
    products = Product.objects.filter(status=1)
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        products = products.order_by('-sales')  # 按销量降序
    elif sort == 'price_asc':
        products = products.order_by('price')  # 按价格升序
    elif sort == 'price_desc':
        products = products.order_by('-price')  # 按价格降序
    elif sort == 'rating':
        # 使用注解获取平均评分并排序
        products = products.annotate(avg_rating=Avg('comments__rating')).order_by('-avg_rating')
    # 默认排序（最新上架）
    else:
        products = products.order_by('-created_time')
    
    # 分页处理，每页显示12个商品
    paginator = Paginator(products, 12)
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有分类，用于导航栏显示
    categories = Category.objects.all()
    
    # 构建上下文数据
    context = {
        'page_obj': page_obj,  # 当前页的商品数据
        'categories': categories,  # 所有分类
        'current_sort': sort,  # 当前排序方式
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 普通请求返回完整页面
    return render(request, 'product/list.html', context)


def category_view(request, category_id):
    """
    分类视图 - 显示特定主分类下的商品
    包括该分类下所有子分类的商品
    
    Args:
        request: HttpRequest对象
        category_id: 主分类ID
        
    Returns:
        HttpResponse: 渲染后的分类页面
    """
    # 处理Ajax请求时不使用缓存
    if request.GET.get('ajax') == '1':
        return _category_view_uncached(request, category_id)
    
    return _category_view_uncached(request, category_id)


def _category_view_uncached(request, category_id):
    """
    分类视图的非缓存版本 - 内部实现函数
    获取特定主分类下的商品数据，处理排序、分页等逻辑
    
    Args:
        request: HttpRequest对象
        category_id: 主分类ID
        
    Returns:
        HttpResponse: 渲染后的分类页面或部分HTML(AJAX请求)
    """
    # 获取分类信息，如果不存在则返回404
    category = get_object_or_404(Category, id=category_id)
    # 获取该分类下的所有子分类
    subcategories = category.subcategories.all()
    
    # 获取该分类下的所有商品
    product_types = []
    for subcategory in subcategories:
        # 收集所有子分类下的商品类型
        product_types.extend(subcategory.product_types.all())
    
    # 获取这些商品类型下的所有上架商品
    products = Product.objects.filter(product_type__in=product_types, status=1)
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        products = products.order_by('-sales')  # 按销量降序
    elif sort == 'price_asc':
        products = products.order_by('price')  # 按价格升序
    elif sort == 'price_desc':
        products = products.order_by('-price')  # 按价格降序
    elif sort == 'rating':
        # 使用注解获取平均评分并排序
        products = products.annotate(avg_rating=Avg('comments__rating')).order_by('-avg_rating')
    # 默认排序（最新上架）
    else:
        products = products.order_by('-created_time')
    
    # 分页处理
    paginator = Paginator(products, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有主分类，用于导航栏显示
    all_categories_for_nav = Category.objects.all()
    
    # 添加调试输出，详细展示all_categories_for_nav的结构

    print("\n===== DEBUG: all_categories_for_nav 结构 =====")
    print(f"all_categories_for_nav类型: {type(all_categories_for_nav)}")
    print(f"all_categories_for_nav数量: {all_categories_for_nav.count()}")

    # 遍历输出一级分类及其子分类
    for i, category in enumerate(all_categories_for_nav):
        print(f"\n第{i+1}个一级分类: {category.name} (ID: {category.id})")

        # 输出该一级分类下的二级分类
        subcategories = category.subcategories.all()
        print(f"  二级分类数量: {subcategories.count()}")

        for j, subcategory in enumerate(subcategories):
            print(f"  {j+1}. 二级分类: {subcategory.name} (ID: {subcategory.id})")

            # 输出该二级分类下的三级分类
            product_types = subcategory.product_types.all()
            print(f"    三级分类数量: {product_types.count()}")

            for k, product_type in enumerate(product_types):
                print(f"    {k+1}. 三级分类: {product_type.name} (ID: {product_type.id})")

    print("===== DEBUG END =====\n")
    
    # 构建上下文数据
    context = {
        'category': category,  # 当前分类
        'subcategories': subcategories,  # 子分类列表
        'page_obj': page_obj,  # 当前页的商品数据
        'subcategory_id': None,  # 当前视图无选中子分类
        'categories': all_categories_for_nav,  # 所有分类(用于导航)
        'current_sort': sort,  # 当前排序方式
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 渲染分类页面
    return render(request, 'product/category.html', context)


def subcategory_view(request, subcategory_id):
    """
    子分类视图 - 显示特定子分类下的商品
    
    Args:
        request: HttpRequest对象
        subcategory_id: 子分类ID
        
    Returns:
        HttpResponse: 渲染后的子分类页面
    """
    # 获取子分类信息，如果不存在则返回404
    subcategory = get_object_or_404(SubCategory, id=subcategory_id)
    # 获取该子分类下的所有商品类型
    product_types = subcategory.product_types.all()
    
    # 获取这些商品类型下的所有上架商品
    products = Product.objects.filter(product_type__in=product_types, status=1)
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        products = products.order_by('-sales')  # 按销量降序
    elif sort == 'price_asc':
        products = products.order_by('price')  # 按价格升序
    elif sort == 'price_desc':
        products = products.order_by('-price')  # 按价格降序
    elif sort == 'rating':
        # 使用注解获取平均评分并排序
        products = products.annotate(avg_rating=Avg('comments__rating')).order_by('-avg_rating')
    # 默认排序（最新上架）
    else:
        products = products.order_by('-created_time')
    
    # 分页处理
    paginator = Paginator(products, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有主分类，用于导航栏显示
    all_categories_for_nav = Category.objects.all()

    # 添加调试输出，详细展示all_categories_for_nav的结构

    print("\n===== DEBUG: all_categories_for_nav 结构 =====")
    print(f"all_categories_for_nav类型: {type(all_categories_for_nav)}")
    print(f"all_categories_for_nav数量: {all_categories_for_nav.count()}")

    # 遍历输出一级分类及其子分类
    for i, category in enumerate(all_categories_for_nav):
        print(f"\n第{i + 1}个一级分类: {category.name} (ID: {category.id})")

        # 输出该一级分类下的二级分类
        subcategories = category.subcategories.all()
        print(f"  二级分类数量: {subcategories.count()}")

        for j, subcategory in enumerate(subcategories):
            print(f"  {j + 1}. 二级分类: {subcategory.name} (ID: {subcategory.id})")

            # 输出该二级分类下的三级分类
            product_types = subcategory.product_types.all()
            print(f"    三级分类数量: {product_types.count()}")

            for k, product_type in enumerate(product_types):
                print(f"    {k + 1}. 三级分类: {product_type.name} (ID: {product_type.id})")

    print("===== DEBUG END =====\n")


    # 构建上下文数据
    context = {
        'subcategory': subcategory,  # 当前子分类
        'product_types': product_types,  # 商品类型列表
        'page_obj': page_obj,  # 当前页的商品数据
        'product_type_id': None,  # 当前视图无选中商品类型
        'categories': all_categories_for_nav,  # 所有分类(用于导航)
        'current_sort': sort,  # 当前排序方式
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 渲染子分类页面
    return render(request, 'product/subcategory.html', context)


def product_type_view(request, product_type_id):
    """
    商品类型视图 - 显示特定商品类型下的商品
    
    Args:
        request: HttpRequest对象
        product_type_id: 商品类型ID
        
    Returns:
        HttpResponse: 渲染后的商品类型页面
    """
    # 获取商品类型信息，如果不存在则返回404
    product_type = get_object_or_404(ProductType, id=product_type_id)
    # 获取该商品类型下的所有上架商品
    products = Product.objects.filter(product_type=product_type, status=1)
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        products = products.order_by('-sales')  # 按销量降序
    elif sort == 'price_asc':
        products = products.order_by('price')  # 按价格升序
    elif sort == 'price_desc':
        products = products.order_by('-price')  # 按价格降序
    elif sort == 'rating':
        # 使用注解获取平均评分并排序
        products = products.annotate(avg_rating=Avg('comments__rating')).order_by('-avg_rating')
    # 默认排序（最新上架）
    else:
        products = products.order_by('-created_time')
    
    # 分页处理
    paginator = Paginator(products, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有主分类，用于导航栏显示
    all_categories_for_nav = Category.objects.all()

    # 添加调试输出，详细展示all_categories_for_nav的结构

    print("\n===== DEBUG: all_categories_for_nav 结构 =====")
    print(f"all_categories_for_nav类型: {type(all_categories_for_nav)}")
    print(f"all_categories_for_nav数量: {all_categories_for_nav.count()}")

    # 遍历输出一级分类及其子分类
    for i, category in enumerate(all_categories_for_nav):
        print(f"\n第{i + 1}个一级分类: {category.name} (ID: {category.id})")

        # 输出该一级分类下的二级分类
        subcategories = category.subcategories.all()
        print(f"  二级分类数量: {subcategories.count()}")

        for j, subcategory in enumerate(subcategories):
            print(f"  {j + 1}. 二级分类: {subcategory.name} (ID: {subcategory.id})")

            # 输出该二级分类下的三级分类
            product_types = subcategory.product_types.all()
            print(f"    三级分类数量: {product_types.count()}")

            for k, product_type in enumerate(product_types):
                print(f"    {k + 1}. 三级分类: {product_type.name} (ID: {product_type.id})")

    print("===== DEBUG END =====\n")

    # 构建上下文数据
    context = {
        'product_type': product_type,  # 当前商品类型
        'page_obj': page_obj,  # 当前页的商品数据
        'product_type_id': product_type.id,  # 当前选中的商品类型ID
        'categories': all_categories_for_nav,  # 所有分类(用于导航)
        'current_sort': sort,  # 当前排序方式
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 渲染商品类型页面
    return render(request, 'product/product_type.html', context)


def product_detail(request, product_id):
    """
    商品详情视图 - 显示单个商品的详细信息
    包括商品基本信息、详情图片、评论和相关商品
    
    Args:
        request: HttpRequest对象
        product_id: 商品ID
        
    Returns:
        HttpResponse: 渲染后的商品详情页面
    """
    # 从数据库获取商品信息，如果不存在则返回404
    product = get_object_or_404(Product, id=product_id)
    
    # 处理商品详情图片
    parsed_detail_images = []
    if product.detail_images:
        try:
            # 检查detail_images是否已经是列表类型
            if isinstance(product.detail_images, list):
                # 处理路径，使其适应static目录结构
                parsed_detail_images = []
                for item in product.detail_images:
                    if isinstance(item, (str, bytes)):
                        # 删除可能存在的'static/'前缀，因为{% static %}标签会自动添加
                        path = str(item).replace('\\', '/')
                        if path.startswith('static/'):
                            path = path[7:]  # 移除'static/'前缀
                        parsed_detail_images.append(path)
            else:
                # 如果是字符串，则尝试解析JSON
                loaded_images = json.loads(product.detail_images)
                if isinstance(loaded_images, list):
                    parsed_detail_images = []
                    for item in loaded_images:
                        if isinstance(item, (str, bytes)):
                            # 处理同上
                            path = str(item).replace('\\', '/')
                            if path.startswith('static/'):
                                path = path[7:]
                            parsed_detail_images.append(path)
        except (json.JSONDecodeError, TypeError):
            # 解析失败则为空列表
            parsed_detail_images = []
    
    # 获取商品评论，按时间降序排序
    comments = product.comments.all().order_by('-created_time')
    
    # 获取相关商品(同类型的其他商品)，最多6个
    related_products = Product.objects.filter(
        product_type=product.product_type, 
        status=1
    ).exclude(id=product.id)[:6]
    
    # 检查当前用户的购物车中是否已有该商品
    in_cart = False
    if request.user.is_authenticated:
        in_cart = CartItem.objects.filter(user=request.user, product=product).exists()
    
    # 构建上下文数据
    context = {
        'product': product,  # 商品信息
        'parsed_detail_images': parsed_detail_images,  # 处理后的详情图片
        'comments': comments,  # 商品评论
        'related_products': related_products,  # 相关商品
        'in_cart': in_cart,  # 是否已在购物车中
    }
    
    return render(request, 'product/detail.html', context)


def search(request):
    """
    商品搜索视图
    根据关键词搜索商品，支持排序和分页
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的搜索结果页面
    """
    # 获取搜索关键词
    query = request.GET.get('q', '')
    
    if query:
        # 使用Q对象组合多个查询条件，实现多字段搜索
        products = Product.objects.filter(
            Q(name__icontains=query) | 
            Q(description__icontains=query) | 
            Q(product_type__name__icontains=query),
            status=1  # 只搜索上架商品
        ).distinct()  # 使用distinct避免重复结果
    else:
        # 如果没有搜索关键词，返回空查询集
        products = Product.objects.none()
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        products = products.order_by('-sales')  # 按销量降序
    elif sort == 'price_asc':
        products = products.order_by('price')  # 按价格升序
    elif sort == 'price_desc':
        products = products.order_by('-price')  # 按价格降序
    elif sort == 'rating':
        # 使用注解获取平均评分并排序
        products = products.annotate(avg_rating=Avg('comments__rating')).order_by('-avg_rating')
    # 默认排序（最新上架）
    else:
        products = products.order_by('-created_time')
    
    # 分页处理
    paginator = Paginator(products, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 构建上下文数据
    context = {
        'query': query,  # 搜索关键词
        'page_obj': page_obj,  # 当前页的商品数据
        'current_sort': sort,  # 当前排序方式
    }
    
    # 渲染搜索结果页面
    return render(request, 'product/search.html', context)


def home_page(request):
    """
    主页视图 - 网站首页
    显示分类、热门商品、轮播图等内容
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的首页
    """
    # 获取所有主分类及其子分类
    categories = Category.objects.all()
    
    # 添加调试输出，详细展示categories的结构
    if request.GET.get('debug') == '1':
        print("\n===== DEBUG: categories 结构 =====")
        print(f"categories类型: {type(categories)}")
        print(f"categories数量: {categories.count()}")
        
        # 遍历输出一级分类及其子分类
        for i, category in enumerate(categories):
            print(f"\n第{i+1}个一级分类: {category.name} (ID: {category.id})")
            
            # 输出该一级分类下的二级分类
            subcategories = category.subcategories.all()
            print(f"  二级分类数量: {subcategories.count()}")
            
            for j, subcategory in enumerate(subcategories):
                print(f"  {j+1}. 二级分类: {subcategory.name} (ID: {subcategory.id})")
                
                # 输出该二级分类下的三级分类
                product_types = subcategory.product_types.all()
                print(f"    三级分类数量: {product_types.count()}")
                
                for k, product_type in enumerate(product_types):
                    print(f"    {k+1}. 三级分类: {product_type.name} (ID: {product_type.id})")
        
        print("===== DEBUG END =====\n")
    
    # 获取热门商品（这里简单地获取最新的8个商品）
    hot_products = list(Product.objects.filter(status=1).order_by('-created_time')[:8])
    
    # 获取每个主分类下的4个热门商品，构建推荐商品列表
    category_products = []
    for category in categories:
        # 获取该分类下所有子分类
        subcategories = category.subcategories.all()
        
        # 获取所有子分类下的商品类型
        product_types = []
        for subcategory in subcategories:
            product_types.extend(subcategory.product_types.all())
        
        # 获取该分类下的热门商品
        products = Product.objects.filter(
            product_type__in=product_types, 
            status=1
        ).order_by('-created_time')[:4]  # 每个分类取4个最新商品
        
        # 如果该分类有商品，则添加到列表中
        if products.exists():
            category_products.append({
                'category': category,
                'products': list(products)
            })
    
    # 创建轮播图数据（每个轮播图关联一个分类）
    carousel_items = []
    
    # 确保有足够的分类可用
    available_categories = categories[:3] if len(categories) >= 3 else categories
    
    # 创建轮播图数据，关联前3个分类
    carousel_images = [
        'static/img/carousel/carousel1.jpg',  # 电子产品
        'static/img/carousel/carousel2.jpg',  # 时尚服饰
        'static/img/carousel/carousel3.jpg',  # 家居生活
    ]
    
    carousel_titles = ['最新电子产品', '时尚服饰', '家居生活']
    carousel_subtitles = ['探索我们的高科技产品系列', '发现最新的时尚趋势', '提升您的家居体验']
    
    # 将轮播图与分类关联
    for i, category in enumerate(available_categories):
        if i < len(carousel_images):
            carousel_items.append({
                'image': carousel_images[i],
                'title': carousel_titles[i],
                'subtitle': carousel_subtitles[i],
                'category_id': category.id,
                'category_name': category.name
            })
    
    # 如果分类不足3个，用默认数据填充
    while len(carousel_items) < 3:
        index = len(carousel_items)
        carousel_items.append({
            'image': carousel_images[index],
            'title': carousel_titles[index],
            'subtitle': carousel_subtitles[index],
            'category_id': None,
            'category_name': '全部商品'
        })
    
    # 构建上下文数据
    context = {
        'categories': categories,  # 所有分类
        'hot_products': hot_products,  # 热门商品
        'category_products': category_products,  # 分类商品
        'carousel_items': carousel_items,  # 轮播图数据
    }
    
    return render(request, 'index.html', context)


def add_to_cart(request, product_id):
    """
    添加商品到购物车视图
    支持AJAX请求和普通表单提交
    
    Args:
        request: HttpRequest对象
        product_id: 商品ID
        
    Returns:
        HttpResponse或JsonResponse: 重定向或JSON响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 如果是AJAX请求，返回JSON响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'redirect_url': login_url
            })
        # 添加消息提示
        messages.info(request, '请先登录后再添加商品到购物车')
        return redirect(login_url)
    
    # 获取商品信息，如果不存在则返回404
    product = get_object_or_404(Product, id=product_id)
    
    # 检查库存
    if product.stock <= 0:
        # 库存不足，返回错误信息
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': f'抱歉，{product.name}已售罄'
            })
        messages.error(request, '抱歉，该商品已售罄')
        return redirect('product_detail', product_id=product_id)
    
    # 获取要添加的数量，默认为1
    quantity = int(request.POST.get('quantity', 1))
    
    # 验证数量
    if quantity <= 0:
        quantity = 1
    
    # 检查购物车中是否已有该商品
    cart_item, created = CartItem.objects.get_or_create(
        user=request.user,
        product=product,
        defaults={'quantity': min(quantity, product.stock)}  # 确保不超过库存
    )
    
    # 如果购物车中已有该商品，增加数量
    if not created:
        # 计算新数量，确保不超过库存
        new_quantity = cart_item.quantity + quantity
        
        if new_quantity > product.stock:
            # 如果新数量超过库存，调整为最大可购买数量
            cart_item.quantity = product.stock
            cart_item.save()
            message = f'商品"{product.name}"库存不足，已自动调整为最大可购买数量{product.stock}件'
            
            # 根据请求类型返回不同响应
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': message,
                    'cart_count': CartItem.objects.filter(user=request.user).count()
                })
            messages.warning(request, message)
        else:
            # 正常更新数量
            cart_item.quantity = new_quantity
            cart_item.save()
            message = f'已将{product.name}的数量更新为{cart_item.quantity}'
            
            # 根据请求类型返回不同响应
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': message,
                    'cart_count': CartItem.objects.filter(user=request.user).count()
                })
            messages.success(request, message)
    else:
        # 处理新创建的购物车项
        if quantity > product.stock:
            # 如果添加数量超过库存，调整为最大可购买数量
            cart_item.quantity = product.stock
            cart_item.save()
            message = f'商品"{product.name}"库存不足，已自动调整为最大可购买数量{product.stock}件'
            
            # 根据请求类型返回不同响应
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': message,
                    'cart_count': CartItem.objects.filter(user=request.user).count()
                })
            messages.warning(request, message)
        else:
            message = f'已将{product.name}添加到购物车'
            
            # 根据请求类型返回不同响应
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': message,
                    'cart_count': CartItem.objects.filter(user=request.user).count()
                })
            messages.success(request, message)
    
    # 添加成功后，可以重定向到购物车页面或商品详情页
    next_url = request.POST.get('next')
    if next_url:
        return redirect(next_url)
    return redirect('product_detail', product_id=product_id)


def view_cart(request):
    """
    查看购物车视图 - 显示用户的购物车内容
    计算选中商品的总价和数量
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的购物车页面
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 添加消息提示
        messages.info(request, '请先登录后再查看购物车')
        return redirect(login_url)
    
    # 使用select_related优化查询，一次性获取关联的产品信息，减少数据库查询次数
    cart_items = CartItem.objects.filter(user=request.user).select_related('product')
    
    # 检查商品库存状态，自动取消选中已售罄商品
    for item in cart_items:
        # 确保我们有最新的库存信息
        item.product.refresh_from_db(fields=['stock'])
        
        # 如果商品已售罄但仍被选中，则取消选中
        if item.product.stock <= 0 and item.selected:
            item.selected = False
            item.save()
    
    # 计算总价 (仅考虑有效选中的商品)
    total_price = sum(item.total_price for item in cart_items if item.selected and item.product.stock > 0)
    selected_count = sum(item.quantity for item in cart_items if item.selected and item.product.stock > 0)
    
    # 构建上下文数据
    context = {
        'cart_items': cart_items,  # 购物车商品
        'total_price': total_price,  # 总价
        'selected_count': selected_count,  # 选中商品数量
    }
    
    return render(request, 'product/cart.html', context)


def update_cart(request, item_id):
    """
    更新购物车商品数量视图
    支持AJAX请求和普通表单提交，处理库存不足等异常情况
    
    Args:
        request: HttpRequest对象
        item_id: 购物车项ID
        
    Returns:
        HttpResponse或JsonResponse: 重定向或JSON响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 如果是AJAX请求，返回JSON响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'redirect_url': login_url
            })
        
        # 添加消息提示
        messages.info(request, '请先登录后再操作购物车')
        return redirect(login_url)
    
    # 获取购物车项，确保只能修改自己的购物车
    cart_item = get_object_or_404(CartItem, id=item_id, user=request.user)
    
    # 判断是否为AJAX请求
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
    
    try:
        # 获取新数量
        if request.method == "POST":
            quantity = None
            
            # 尝试从不同的请求格式中获取数量
            if request.content_type and 'application/json' in request.content_type:
                # JSON格式请求
                import json
                try:
                    data = json.loads(request.body)
                    quantity = int(data.get('quantity', 1))
                except json.JSONDecodeError:
                    pass
            
            # 如果没有从JSON中获取到数量，尝试从POST表单中获取
            if quantity is None:
                quantity = int(request.POST.get('quantity', 1))
            
            # 验证数量
            if quantity <= 0:
                # 如果数量为0或负数，则从购物车中删除该商品
                cart_item.delete()
                message = f'已从购物车中移除{cart_item.product.name}'
                success = True
                item_total = 0
                
                if is_ajax:
                    return JsonResponse({
                        'success': success,
                        'message': message,
                        'current_quantity': 0,
                        'item_total': item_total,
                        'current_stock': cart_item.product.stock,
                    })
                else:
                    messages.success(request, message)
                    return redirect('view_cart')
            else:
                # 重新获取商品以确保有最新的库存信息
                product = cart_item.product
                product.refresh_from_db(fields=['stock'])
                
                # 检查库存
                if product.stock < quantity:
                    # 库存不足，自动调整为最大可购买数量
                    adjusted_quantity = max(0, product.stock)  # 确保不为负数
                    
                    if product.stock <= 0:
                        message = f'商品"{product.name}"已售罄'
                    else:
                        message = f'商品"{product.name}"库存不足，已自动调整为最大可购买数量{adjusted_quantity}件'
                    
                    success = False
                    
                    # 更新为最大可购买数量
                    cart_item.quantity = adjusted_quantity
                    cart_item.save()
                    item_total = cart_item.total_price
                    
                    # 如果商品已售罄，自动取消选中状态
                    if product.stock <= 0:
                        cart_item.selected = False
                        cart_item.save()
                    
                    if is_ajax:
                        return JsonResponse({
                            'success': success,
                            'message': message,
                            'error': message,
                            'current_quantity': adjusted_quantity,
                            'item_total': item_total,
                            'current_stock': product.stock,
                        })
                    else:
                        messages.warning(request, message)
                        return redirect('view_cart')
                
                # 更新数量
                cart_item.quantity = quantity
                cart_item.save()
                message = f'已将{cart_item.product.name}的数量更新为{quantity}'
                success = True
                item_total = cart_item.total_price
                
            if is_ajax:
                return JsonResponse({
                    'success': success,
                    'message': message,
                    'current_quantity': quantity if quantity > 0 else 0,
                    'item_total': item_total,
                    'current_stock': product.stock,
                })
            else:
                messages.success(request, message)
                return redirect('view_cart')
    except ValueError:
        # 处理数量格式错误
        message = '请输入有效的数量'
        if is_ajax:
            return JsonResponse({
                'success': False,
                'message': message,
                'error': message,
                'current_quantity': cart_item.quantity,
                'current_stock': cart_item.product.stock,
            })
        else:
            messages.error(request, message)
            return redirect('view_cart')
    except Exception as e:
        # 处理其他错误
        message = f'更新失败: {str(e)}'
        if is_ajax:
            return JsonResponse({
                'success': False,
                'message': message,
                'error': message,
                'current_quantity': cart_item.quantity,
                'current_stock': cart_item.product.stock,
            })
        else:
            messages.error(request, message)
            return redirect('view_cart')


def toggle_select_cart_item(request, item_id):
    """
    切换购物车商品选中状态视图
    用于结算时选择或取消选择商品，支持AJAX请求
    
    Args:
        request: HttpRequest对象
        item_id: 购物车项ID
        
    Returns:
        HttpResponse或JsonResponse: 重定向或JSON响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 如果是AJAX请求，返回JSON响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.content_type == 'application/json':
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'redirect_url': login_url
            })
        
        # 添加消息提示
        messages.info(request, '请先登录后再操作购物车')
        return redirect(login_url)
    
    # 获取购物车项，确保只能修改自己的购物车
    cart_item = get_object_or_404(CartItem, id=item_id, user=request.user)
    
    # 判断是否为AJAX请求
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.content_type == 'application/json'
    
    try:
        if request.method == "POST":
            # 获取最新的商品库存信息
            product = cart_item.product
            product.refresh_from_db(fields=['stock'])
            
            if is_ajax:
                # 从JSON请求中获取选中状态
                import json
                data = json.loads(request.body)
                selected = data.get('selected', None)
                
                # 检查是否尝试选中已售罄商品
                if selected is True and product.stock <= 0:
                    return JsonResponse({
                        'success': False,
                        'error': f'商品"{product.name}"已售罄，无法选择',
                        'current_stock': 0
                    })
                
                # 更新选中状态
                if selected is not None:
                    cart_item.selected = selected
                else:
                    # 切换状态，但如果是从未选中到选中且商品已售罄，则不允许
                    if not cart_item.selected and product.stock <= 0:
                        return JsonResponse({
                            'success': False,
                            'error': f'商品"{product.name}"已售罄，无法选择',
                            'current_stock': 0
                        })
                    cart_item.selected = not cart_item.selected
            else:
                # 非AJAX请求下的切换
                if not cart_item.selected and product.stock <= 0:
                    messages.error(request, f'商品"{product.name}"已售罄，无法选择')
                    return redirect('view_cart')
                cart_item.selected = not cart_item.selected
                
            # 保存更新后的选中状态
            cart_item.save()
            
            if is_ajax:
                # 计算购物车总价
                cart_items = CartItem.objects.filter(user=request.user)
                total_price = sum(item.total_price for item in cart_items if item.selected)
                selected_count = sum(item.quantity for item in cart_items if item.selected)
                
                # 返回JSON响应
                return JsonResponse({
                    'success': True,
                    'selected': cart_item.selected,
                    'total_price': total_price,
                    'selected_count': selected_count,
                    'current_stock': product.stock
                })
            else:
                # 重定向到购物车页面
                return redirect('view_cart')
    except Exception as e:
        # 处理异常
        if is_ajax:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })
        else:
            messages.error(request, f'操作失败: {str(e)}')
            return redirect('view_cart')


def remove_from_cart(request, item_id):
    """
    从购物车中移除商品视图
    支持AJAX请求和普通表单提交
    
    Args:
        request: HttpRequest对象
        item_id: 购物车项ID
        
    Returns:
        HttpResponse或JsonResponse: 重定向或JSON响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 如果是AJAX请求，返回JSON响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.content_type == 'application/json':
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'redirect_url': login_url
            })
        
        # 添加消息提示
        messages.info(request, '请先登录后再操作购物车')
        return redirect(login_url)
    
    # 获取购物车项，确保只能删除自己的购物车项
    cart_item = get_object_or_404(CartItem, id=item_id, user=request.user)
    product_name = cart_item.product.name
    
    # 判断是否为AJAX请求
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.content_type == 'application/json'
    
    try:
        # 删除购物车项
        cart_item.delete()
        
        if is_ajax:
            # 获取购物车剩余商品数量
            cart_count = CartItem.objects.filter(user=request.user).count()
            
            # 计算购物车总价
            cart_items = CartItem.objects.filter(user=request.user)
            total_price = sum(item.total_price for item in cart_items if item.selected)
            selected_count = sum(item.quantity for item in cart_items if item.selected)
            
            # 返回JSON响应
            return JsonResponse({
                'success': True,
                'message': f'已从购物车中移除{product_name}',
                'cart_count': cart_count,
                'total_price': total_price,
                'selected_count': selected_count
            })
        else:
            # 添加成功消息
            messages.success(request, f'已从购物车中移除{product_name}')
            # 重定向到购物车页面
            return redirect('view_cart')
    except Exception as e:
        # 处理异常
        if is_ajax:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })
        else:
            messages.error(request, f'移除失败: {str(e)}')
            return redirect('view_cart')


def remove_from_cart_all(request):
    """
    清空购物车视图
    删除用户购物车中的所有商品
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse或JsonResponse: 重定向或JSON响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 如果是AJAX请求，返回JSON响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'redirect_url': login_url
            })
        
        # 添加消息提示
        messages.info(request, '请先登录后再操作购物车')
        return redirect(login_url)
    
    # 删除用户的所有购物车项
    CartItem.objects.filter(user=request.user).delete()
    
    # 判断是否为AJAX请求
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        return JsonResponse({'success': True})
    
    # 添加成功消息
    messages.success(request, '购物车已清空')
    # 重定向到购物车页面
    return redirect('view_cart')


def checkout_redirect(request):
    """
    结算重定向视图
    从购物车跳转到结算页面，检查是否有选中的商品
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 重定向响应
    """
    # 检查用户是否登录
    if not request.user.is_authenticated:
        # 构建重定向URL，包含next参数指向当前页面
        login_url = reverse('login') + f'?next={request.path}'
        
        # 添加消息提示
        messages.info(request, '请先登录后再进行结算')
        return redirect(login_url)
    
    # 检查是否有选中的商品
    selected_items = CartItem.objects.filter(user=request.user, selected=True)
    
    if not selected_items.exists():
        # 如果没有选中商品，显示警告消息
        messages.warning(request, '请至少选择一件商品进行结算')
        return redirect('view_cart')
    
    # 重定向到结算页面
    return redirect('checkout')


def new_products(request):
    """
    新品上架视图
    显示创建时间在30天内的商品
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的新品页面
    """
    # 获取所有上架的商品
    products = Product.objects.filter(status=1)
    
    # 筛选新品（使用is_new属性）
    new_products_list = [product for product in products if product.is_new]
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        new_products_list.sort(key=lambda x: x.sales, reverse=True)  # 按销量降序
    elif sort == 'price_asc':
        new_products_list.sort(key=lambda x: x.price)  # 按价格升序
    elif sort == 'price_desc':
        new_products_list.sort(key=lambda x: x.price, reverse=True)  # 按价格降序
    # 默认排序（最新上架）
    else:
        new_products_list.sort(key=lambda x: x.created_time, reverse=True)  # 按创建时间降序
    
    # 分页处理
    paginator = Paginator(new_products_list, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有分类，用于导航栏显示
    categories = Category.objects.all()
    
    # 构建上下文数据
    context = {
        'page_obj': page_obj,  # 当前页的商品数据
        'categories': categories,  # 所有分类
        'current_sort': sort,  # 当前排序方式
        'page_title': '新品上架',  # 页面标题
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 渲染新品页面
    return render(request, 'product/list.html', context)


def on_sale_products(request):
    """
    热门促销视图
    显示有折扣的商品(原价大于现价)
    
    Args:
        request: HttpRequest对象
        
    Returns:
        HttpResponse: 渲染后的促销商品页面
    """
    # 获取所有上架的商品
    products = Product.objects.filter(status=1)
    
    # 筛选促销商品（使用is_on_sale属性）
    on_sale_products_list = [product for product in products if product.is_on_sale]
    
    # 获取排序参数
    sort = request.GET.get('sort', 'default')
    
    # 根据排序参数进行排序
    if sort == 'sales':
        on_sale_products_list.sort(key=lambda x: x.sales, reverse=True)  # 按销量降序
    elif sort == 'price_asc':
        on_sale_products_list.sort(key=lambda x: x.price)  # 按价格升序
    elif sort == 'price_desc':
        on_sale_products_list.sort(key=lambda x: x.price, reverse=True)  # 按价格降序
    elif sort == 'discount':
        # 按折扣率排序
        on_sale_products_list.sort(key=lambda x: x.discount_rate, reverse=True)  # 按折扣率降序
    # 默认排序（折扣率）
    else:
        on_sale_products_list.sort(key=lambda x: x.discount_rate, reverse=True)  # 按折扣率降序
    
    # 分页处理
    paginator = Paginator(on_sale_products_list, 12)  # 每页12个商品
    page_number = request.GET.get('page', 1)  # 获取页码，默认为第1页
    page_obj = paginator.get_page(page_number)  # 获取当前页的Page对象
    
    # 获取所有分类，用于导航栏显示
    categories = Category.objects.all()
    
    # 构建上下文数据
    context = {
        'page_obj': page_obj,  # 当前页的商品数据
        'categories': categories,  # 所有分类
        'current_sort': sort,  # 当前排序方式
        'page_title': '热门促销',  # 页面标题
        'show_discount': True,  # 显示折扣标签
    }
    
    # 检查是否为AJAX请求（无限滚动）
    if request.GET.get('ajax') == '1':
        # 如果是AJAX请求，只返回商品列表部分HTML
        return render(request, 'product/product_list_items.html', context)
    
    # 渲染促销商品页面
    return render(request, 'product/list.html', context)